package online

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkStartPublishReqData(data common.P2PStartPublishReqData) error {
	// Check if call ID provided
	if data.CallId == "" {
		return errors.New("call_id is required in start publish request")
	}

	// Check if user ID provided
	if data.UserId == "" {
		return errors.New("user_id is required in start publish request")
	}

	// Check if media information is valid
	if err := common.ValidateMediaInfo(data.Media); err != nil {
		return errors.New("invalid media information in start publish request: " + err.Error())
	}

	// Check if call exists
	if !s.callMgr.CallExists(data.CallId) {
		return errors.New("call does not exist for call_id: " + data.CallId)
	}

	// Check if user exists
	if !s.userMgr.UserExists(data.UserId) {
		return errors.New("user does not exist for user_id: " + data.UserId)
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendSuccessStartPublishResponse(rid string,
	reqData common.P2PStartPublishReqData, connId string) {
	response := common.Message{
		Cmd: common.P2P_START_PUBLISH_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: 0,
			Msg:  "Start publish request processed successfully",
			Data: common.P2PStartPublishResData{
				CallId: reqData.CallId,
				UserId: reqData.UserId,
				Media:  reqData.Media,
			},
		},
	}
	s.dispatcher.Dispatch(response, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendFailStartPublishResponse(rid string, msg string, connId string) {
	response := common.Message{
		Cmd: common.P2P_START_PUBLISH_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: 1,
			Msg:  msg,
			Data: nil,
		},
	}
	s.dispatcher.Dispatch(response, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleStartPublishReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleStartPublishReq")

	var reqData common.P2PStartPublishReqData
	if err := mapstructure.Decode(msg.Data, &reqData); err != nil {
		s.sendFailStartPublishResponse(msg.Rid, err.Error(), connId)
		return nil
	}

	if err := s.checkStartPublishReqData(reqData); err != nil {
		s.sendFailStartPublishResponse(msg.Rid, err.Error(), connId)
		return nil
	}

	peerUserId, err := s.callMgr.GetPeerUserId(reqData.CallId, reqData.UserId)
	if err != nil {
		s.sendFailStartPublishResponse(msg.Rid, "failed to get peer user ID", connId)
		return nil
	}

	peerUser := s.userMgr.GetUserByUserId(peerUserId)
	if peerUser == nil {
		s.sendFailStartPublishResponse(msg.Rid, "cannot find peer user", connId)
		return nil
	}

	if err := s.callMgr.AddPublishMedia(reqData); err != nil {
		s.sendFailStartPublishResponse(msg.Rid, "failed to add publish media", connId)
		return nil
	}

	// 发送响应
	s.sendSuccessStartPublishResponse(msg.Rid, reqData, connId)

	// 发送通知给对端
	s.dispatcher.Dispatch(
		common.Message{
			Cmd:  common.P2P_START_PUBLISH_NOTIFY,
			Rid:  msg.Rid,
			Data: msg.Data,
		},
		s.serviceInfo,
		common.AccessServiceInfo,
		peerUser.ConnId)

	return nil
}
